<!DOCTYPE html>
<script src="/js-test-resources/testharness.js"></script>
<script src="/js-test-resources/testharnessreport.js"></script>
<script>
'use strict';

// These tests test WebSocket handshake throttling, which is a feature of
// Blink's implementation, not part of the web platform. The special throttle
// content::TestWebSocketHandshakeThrottle is used when content_shell is run
// with the --run-web-tests option. It detects the
// content-shell-websocket-delay-ms query parameter in the URL and applies a
// delay of the specified number of milliseconds.
//
// These tests will not function correctly without the --run-web-tests
// option. To debug them interactively you can follow the instructions for a
// "legacy test" in
// https://chromium.googlesource.com/chromium/src/+/master/docs/testing/web_tests.md#Debugging-DevTools-Tests.

async_test(t => {
  const startTime = Date.now();
  const ws = new WebSocket(
      'ws://localhost:8880/echo?content-shell-websocket-delay-ms=250');
  ws.onopen = t.step_func(() => {
    const endTime = Date.now();
    assert_greater_than_equal(endTime - startTime, 250,
                              'elapsed time should be greater than 250ms');
    ws.close();
  });
  ws.onclose = t.step_func(e => {
    assert_true(e.wasClean, 'close handshake should complete successfully');
    t.done();
  });
}, 'throttle should delay connection success');

async_test(t => {
  const startTime = Date.now();
  // The test doesn't have to wait for this delay, so it is extra-long to reduce
  // flakiness on slow bots.
  const ws = new WebSocket(
      'ws://localhost:8880/handshake-error?content-shell-websocket-delay-ms=2000');
  ws.onopen = t.unreached_func('onopen should not be called');
  ws.onclose = t.step_func(e => {
    const endTime = Date.now();
    assert_false(e.wasClean, 'WebSocket should not be cleanly closed');
    assert_less_than(endTime - startTime, 2000,
                     'elapsed time should be less than 2000ms');
    t.done();
  });
}, 'throttle should not delay connection failure');

// Regression test for crbug.com/786776.
async_test(t => {
  // The "echo-request-headers" handler sends a message immediately on connect,
  // then closes.
  const ws = new WebSocket(
      'ws://localhost:8880/echo-request-headers?content-shell-websocket-delay-ms=250');
  let onOpenCalled = false;
  let onMessageCalled = false;
  ws.onopen = () => {
    onOpenCalled = true;
  };
  ws.onmessage = t.step_func(() => {
    assert_true(onOpenCalled, 'onopen should happen before onmessage');
    onMessageCalled = true;
  });
  ws.onclose = t.step_func(e => {
    assert_true(e.wasClean, 'close handshake should complete successfully');
    assert_true(onMessageCalled, 'onmessage should be called');
    t.done();
  });
}, 'throttle should not prevent onmessage events');

</script>
